#pragma once
#include "base/noncopyable.h"
#include "base/mutex.h"

namespace net_tools::base{
namespace detail{

struct Memorypool_point
{
  Memorypool_point(){
    before_ = nullptr;
    next_ = nullptr;
    size_ = 0;
  };
  Memorypool_point* before_;
  Memorypool_point* next_;
  size_t            size_;
};

} // namespace detail
#define MEMORY_POOL_POINT_SIZE sizeof(Memorypool_point)
class Memorypool : noncopyable{
public:
  Memorypool(size_t block_size,size_t block_number);
  ~Memorypool();
  //参数:要取用的区块数量
  void* Get_memory_unlocked(size_t block_number);
  void Free_memory_unlocked(void* paddress);
  void* Get_memory_locked(size_t block_number);
  void Free_memory_locked(void* paddress);
private:
  //地址转换
  void* Change_data_to_block(void* address);
  //地址转换
  void* Change_block_to_data(detail::Memorypool_point* address);
  //链表插入 pbfore -> pnext => pbfore -> pmemory_pool_point -> pnext
  void Point_insert(detail::Memorypool_point* pbefore,detail::Memorypool_point* pmemory_pool_point);
  //链表删除 pbfore -> pmemory_pool_point -> pnext => pbfore -> pnext
  void Point_cut(detail::Memorypool_point* pmemory_pool_point); //将可用节点变为占用节点 切断前后连接
  //初始记录块创建
  //返回首位记录块
  detail::Memorypool_point* Point_create(void* paddress,const size_t size);
  //根据记录块首部创建尾部记录块
  void Point_back_create(detail::Memorypool_point* paddress);

  void* pmemory_data_; //数据块起始地址
  void* pmemory_data_end_; //数据块结束地址
  void* pmemory_pool_; //链表起始地址 及内存池起始地址

  detail::Memorypool_point* help_point_head_;
  detail::Memorypool_point* help_point_back_;

  size_t memory_pool_size_;//整个内存池大小
  size_t memory_pool_data_size_; //内存池数据大小

  size_t block_number_; //数据块块数量
  size_t block_size_; //数据块块大小
  size_t block_size_move_;
  size_t free_block_number_;

  Mutex mutex_;
};

} // namespace net_tools::base